#pragma once

#include "../utility/Singleton.h"
#include "MemoryStack.h"
#include "MemoryPool.h"
#include "../Utility/Predeclare.h"

//#ifdef NB_CORE_MEMORY_IMP
//	#define NB_API NB_API_EXPORT  
//#else
//	#define NB_API NB_API_IMPORT  
//#endif

namespace EngineCore {

	class MemoryManager;

	class MemoryManager : public Singleton<MemoryManager>
	{
		friend class Singleton<MemoryManager>;
	public:	
		~MemoryManager();
		MemoryStack& AllocMemoryStack();

		template<class T, class... _types> 
		static std::shared_ptr<T> Create(_types&& ... _args);

		template<class T> 
		static void Destroy(T*);

	protected:
		MemoryManager();
		memory_address AllocMemory(memory_size size);
		void RetriveMemory(memory_address);
	};

	

	template<class T,class... _types>
	std::shared_ptr<T>  MemoryManager::Create(_types&& ... _args)
	{
		memory_size size = sizeof(T);
		memory_address adr = _instance->AllocMemory(size);
		T* objPtr = new(adr) T(std::forward<_types>(_args)...);
		return std::shared_ptr<T>(objPtr , Destroy<T>);
	}


	template<class T>
	void MemoryManager::Destroy(T * objPtr)
	{
		objPtr->~T();
		_instance->RetriveMemory(reinterpret_cast<memory_address>(objPtr));
	}
}
